#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>


#if defined(___SYS_I486)
#define ___SYS "i486"
#if !defined(___SYS_I386)
#define ___SYS_I386
#endif
#elif defined(___SYS_I386)
#define ___SYS "i386"
#else
#error Missing system
#endif
#if defined(___OS_WIN)
#define ___OS "win32"
#elif defined(___OS_LIN)
#define ___OS "linux"
#else
#error Missing OS
#endif
#if defined(___SYS_I386)
#if !defined(___LSB)
#define ___LSB
#endif
#endif
#if !defined(___LSB) && !defined(___MSB)
#error Missing byteorder
#endif
#if defined(___LSB) && defined(___MSB)
#error Invalid byteorder
#endif


typedef void xx;
typedef   signed char  I1;
typedef unsigned char  N1;
typedef   signed short int I2;
typedef unsigned short int N2;
typedef   signed long  int I4;
typedef unsigned long  int N4;
typedef xx *Ptr;
typedef N1 *Str;
typedef N4 (*fFun)(N4 par);


#define S                (Str)
#define CS               char *
#define Bit(n)           (1ul<<(n))
#define Typ(t,v)         ((t)(v))
#define mp1(p,n)         Typ(N1 *,Typ(N1 *,p)+(n))
#define mp2(p,n)         Typ(N2 *,Typ(N1 *,p)+(n))
#define mp4(p,n)         Typ(N4 *,Typ(N1 *,p)+(n))
#define mn1(p,n)         (*mp1(p,n))
#define mn2(p,n)         (*mp2(p,n))
#define mn4(p,n)         (*mp4(p,n))
#define BEG              do {
#define END              } while (0)
#define ERR0(s)          BEG fprintf(stderr,s "\n"); \
                         fflush(stdout); fflush(stderr); \
                         return (-1); END
#define ERR1(s,n1)       BEG fprintf(stderr,s "\n",n1); \
                         fflush(stdout); fflush(stderr); \
                         return (-1); END
#define ERR2(s,n1,n2)    BEG fprintf(stderr,s "\n",n1,n2); \
                         fflush(stdout); fflush(stderr); \
                         return (-1); END
#define ERR3(s,n1,n2,n3) BEG fprintf(stderr,s "\n",n1,n2,n3); \
                         fflush(stdout); fflush(stderr); \
                         return (-1); END
#define FileOpenRead     Bit(0)
#define FileOpenWrite    Bit(1)


#define BUFLEN (256ul*1024ul)
#define TMPLEN 4096ul
#define MACNUM 1024ul
#define VALNUM 1024ul
#define NAMLEN 32
typedef struct _tMac
{ N2 sum,nl;
  N1 nam[NAMLEN];
  N1 *txt; N4 tl;
} tMac;
typedef struct _tVal
{ N4 len; Str val;
} tVal;
static tMac mac[MACNUM]={};
static tVal val[VALNUM]={};
static N4 mlen=0,vlen=0;
static N1 *buf=NULL;
static N4 bpos=0,blen=0;
static int out=-1;


static Ptr MemGet(N4 len)
{ if (!len) return (NULL);
  return (malloc(len));
}
static xx MemRel(Ptr p)
{ if (p) free(p);
}
static xx MemCpy(Str s1,Str s2,N4 l1)
{ if (!s1 || !s2) return;
  if (s1==s2) return;
  if (s1>=s2)
  { while (l1--) *s2++=*s1++;
  } else
  { s1+=l1-1; s2+=l1-1;
    while (l1--) *s2--=*s1--;
  }
}
static Str MemCmp(Str s1,Str s2,N4 l1)
{ if (!s1) return (s2);
  if (!s2) return (s1);
  for (;l1 && *s1==*s2;++s1,++s2,--l1);
  return (l1?s1:NULL);
}
static N4 StrLen(Str s1)
{ N4 i1;
  if (!s1) return (0);
  for (i1=0;*s1++;++i1);
  return (i1);
}
static Str StrCmp(Str s1,Str s2)
{ if (!s1 || !s2)
  { if (s1) return (*s1?s1:NULL);
    if (s2) return (*s2?s2:NULL);
  }
  for (;*s1 && *s1==*s2;++s1,++s2);
  return ((*s1==*s2)?NULL:s1);
}
int getinp(N1 spc,N4 *x,N4 *y);
xx putout(N1 cc);
N1 *Num2Str(N1 sn,N1 bs,N4 num,N1 *s1,N1 l1);
N4 StrH2Num(N1 *buf);
N4 StrD2Num(N1 *buf);
N4 Str2Num(N1 *buf);
N4 macs(N1 cc,N1 *bk,N1 *spc,N4 *x,N4 *y);
// File
N4 FileCheck(Str nam,N4 *len,N4 *tms);
N4 FileOpen(N1 mod,Str nam);
xx FileClose(N4 id);
N4 FileRead(N4 id,Ptr buf,N4 len);
N4 FileWrite(N4 id,Ptr buf,N4 len);


int main(int argc,char **argv)
{ N1 spc=0; N4 x=0,y=0;
  int ii; N1 cc,bk=0;
  N4 n1;

#if defined(___OS_WIN)
  setmode(fileno(stdin),O_BINARY);
  setmode(fileno(stdout),O_BINARY);
  setmode(fileno(stderr),O_BINARY);
#endif

  if (!(buf=MemGet(BUFLEN)))
    ERR0("Error: Buf: Len");
  while (1)
  { // Input
    ii=getinp(spc,&x,&y);
    if (ii==-1) break;
    else cc=(N1)ii;
    // Filter
    n1=macs(cc,&bk,&spc,&x,&y);
    if (n1==-1) return (-1);
    if (n1==1) continue;
    if (n1==2) break;
    // Output
    putout(bk=cc);
  }
  MemRel(buf); if (out!=-1)
    fputc(out,stdout);
  fflush(stdout); return (0);
}

//====================================================================

int getinp(N1 spc,N4 *x,N4 *y)
{ int ii; N1 cc;
  if (!x || !y)
    ERR0("Error: Input: Param");
  while (bpos<blen)
  { ii=(N4)buf[bpos++];
    if (bpos==blen)
      bpos=blen=0;
    if (spc)
      switch (ii)
    { case '\n':
      case '\r':
      case '\t':
      case ' ':
        continue;
    }
    return (ii);
  }
  if ((ii=fgetc(stdin))==-1)
    return (-1);
  else cc=(N1)ii;
  if (cc!='\n') ++*x;
  else { ++*y; *x=0; }
  return (ii);
}

xx putout(N1 cc)
{ if (out!=-1)
    fputc(out,stdout);
  out=(N4)cc;
}

N1 *Num2Str(N1 sn,N1 bs,N4 num,N1 *s1,N1 l1)
{ if (!s1) return (NULL);
  s1+=9; *s1--=0;
  if (sn)
  { if (num&Bit(31))
    { num=-num; }
    else sn=0;
  }
  if (!num && !l1) *s1--='0';
  else while (num || l1)
  { if (l1) --l1;
    switch (bs)
    { case 10:
        *s1=num%10+'0';
        --s1; num/=10;
        break;
      case 16:
        *s1=num&0xF;
        *s1+=((*s1<10)?'0':'A'-10);
        --s1; num>>=4;
        break;
      default: return (NULL);
    }
  }
  if (sn) *s1--='-';
  return (s1+1);
}

N4 StrH2Num(N1 *buf)
{ N4 num=0; N1 c1;

  if (!buf) return (0);
  for (;*buf;++buf)
  { if ('0'<=*buf && *buf<='9')
      c1=*buf-'0'; else
      c1=*buf-'A'+10;
    num=(num<<4)|c1;
  }

  return (num);
}

N4 StrD2Num(N1 *buf)
{ N4 num=0;

  if (!buf) return (0);
  for (;*buf;++buf)
    num=(num*10)+(*buf-'0');

  return (num);
}

N4 Str2Num(N1 *buf)
{ N4 n1; N1 sn=0;
  if (!buf || !*buf) return (0);
  if (*buf=='+') ++buf; else
  if (*buf=='-') { sn=1; ++buf; }
  if (*buf=='x') n1=StrH2Num(buf+1);
  else n1=StrD2Num(buf);
  if (sn) n1=-n1;
  return (n1);
}

//============= Macro ================================================

N4 getm1(N1 iex,N1 *s1,N4 l1,
  N1 c1,N1 c2,N4 *x,N4 *y)
{ int ii; N1 cc,esc=0; N4 i1;

  for (i1=0;i1<l1;)
  { if ((ii=getinp(0,x,y))==-1)
      ERR2("Error: (%lu,%lu): Macro: EOF",*y,*x);
    else cc=(N1)ii;
    if (!esc)
    { if (cc=='\\' && iex) esc=1;
      if (cc==c1) break;
      if (cc==c2) cc=c1;
    } else esc=0;
    if (!esc) s1[i1++]=cc;
  }
  if (!l1 || i1==l1)
    ERR2("Error: (%lu,%lu): Macro: StrLen",*y,*x);
  s1[i1]=0; return (i1);
}

N4 getm2(N1 iex,N1 *s1,N4 l1,N4 *x,N4 *y)
{ int ii; N1 cc,esc=0; N4 i1;

  for (i1=0;i1<l1;)
  { if ((ii=getinp(0,x,y))==-1) break;
    else cc=(N1)ii;
    if (!esc)
    { if (cc=='\\' && iex) esc=1;
      else switch (cc)
      { case '\n':
        case '\r':
        case '\t':
        case ' ':
          MemCpy(buf+bpos,buf+bpos+1,blen-bpos);
          MemCpy(&cc,buf+bpos,1); ++blen;
          cc=0; break;
      }
      if (!cc) break;
    } else esc=0;
    if (!esc) s1[i1++]=cc;
  }
  if (!l1 || i1==l1)
    ERR2("Error: (%lu,%lu): Macro: StrLen",*y,*x);
  s1[i1]=0; return (i1);
}

N2 sum1(N1 *s1,N1 l1)
{ N2 sum=0;
  while (l1--) sum+=*s1++;
  return (sum);
}

N4 mac1(N1 *s1,N1 l1)
{ N4 i0=-1,i1; N2 sum;
  tMac *m1=mac+mlen-1;

  if (!l1) return (-1);
  sum=sum1(s1,l1);
  for (i1=mlen-1;i1+1;--i1,--m1)
  { if (m1->nl==0) i0=i1;
    if (m1->sum!=sum) continue;
    if (m1->nl!=l1) continue;
    if (MemCmp(m1->nam,s1,l1)) continue;
    return (i1);
  }
  if (i0==-1 && mlen<MACNUM)
  { i0=mlen; ++mlen; }
  return (i0);
}

N4 mac2(xx)
{ N4 i1,i2;

  if (mlen==MACNUM)
  { for (i1=i2=0;i2<mlen;++i1,++i2)
    { while (i2<mlen && !mac[i2].nl) ++i2;
      if (i2==mlen) break;
      if (i1==i2) continue;
      mac[i1]=mac[i2];
      mac[i2].nl=0;
      mac[i2].txt=NULL;
    }
    mlen=i1;
  }
  if (mlen==MACNUM)
    return (-1);
  return (mlen++);
}

#define MacOp3Beg \
  if (vlen<3) \
    ERR2("Error: (%lu,%lu): ?&: Param",*y,*x); \
  i1=Str2Num(val[vlen-3].val); \
  i2=Str2Num(val[vlen-2].val);
#define MacOp3End \
  i1=StrLen(p1=Num2Str(0,10,i1,tmp,0)); \
  if (!(p2=MemGet(i1+1))) \
    ERR2("Error: (%lu,%lu): ?&: Nomem",*y,*x); \
  MemRel(val[--vlen].val); \
  MemRel(val[--vlen].val); \
  MemRel(val[vlen-1].val); \
  val[vlen-1].len=i1; val[vlen-1].val=p2; \
  MemCpy(p1,p2,i1); p2[i1]=0;
#define MacOp3IBeg \
  if (vlen<3) \
    ERR2("Error: (%lu,%lu): ?&: Param",*y,*x); \
  j1=Str2Num(val[vlen-3].val); \
  j2=Str2Num(val[vlen-2].val);
#define MacOp3IEnd \
  i1=StrLen(p1=Num2Str(1,10,j1,tmp,0)); \
  if (!(p2=MemGet(i1+1))) \
    ERR2("Error: (%lu,%lu): ?&: Nomem",*y,*x); \
  MemRel(val[--vlen].val); \
  MemRel(val[--vlen].val); \
  MemRel(val[vlen-1].val); \
  val[vlen-1].len=i1; val[vlen-1].val=p2; \
  MemCpy(p1,p2,i1); p2[i1]=0;

N4 macs(N1 cc,N1 *bk,N1 *spc,N4 *x,N4 *y)
{ N4 i1,i2,i3; I4 j1,j2;
  Str p1,p2; N1 ok=0;
  tMac *m1; N1 tmp[TMPLEN];

  if (*bk!='?' && cc=='%')
  { // %<text> : <text>
    if (vlen==VALNUM)
      ERR2("Error: (%lu,%lu): %%text: ValNum",*y,*x);
    i1=getm2(1,tmp,TMPLEN,x,y);
    if (i1==-1) return (-1);
    if (!(p1=MemGet(i1+1)))
      ERR2("Error: (%lu,%lu): %%text: Nomem",*y,*x);
    val[vlen].len=i1; val[vlen].val=p1;
    MemCpy(tmp,p1,i1); p1[i1]=0; ++vlen;
    putout(*bk=0); out=-1; return (1);
  }
  if (*bk=='?') switch (cc)
  { case ':': ok=1;
      fputc('?',stdout);
      break;
    case ';' : ok=1;
      fputc('%',stdout);
      break;
    case '.': ok=2;
      break;
    case '`': ok=1;
      // ?`text` : <text>
      if (vlen==VALNUM)
        ERR2("Error: (%lu,%lu): ?`text`: ValNum",*y,*x);
      i1=getm1(1,tmp,TMPLEN,'`','\'',x,y);
      if (i1==-1) return (-1);
      if (!(p1=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?`text`: Nomem",*y,*x);
      val[vlen].len=i1; val[vlen].val=p1;
      MemCpy(tmp,p1,i1); p1[i1]=0; ++vlen;
      break;
    case 'm': ok=1;
      // <text> ?m : <text> <text>
      if (vlen<1 || vlen==VALNUM)
        ERR2("Error: (%lu,%lu): ?m: Param",*y,*x);
      i1=vlen-1; i2=val[i1].len;
      if (!(p1=MemGet(i2+1)))
        ERR2("Error: (%lu,%lu): ?m: Nomem",*y,*x);
      val[vlen].len=i2; val[vlen].val=p1;
      MemCpy(val[i1].val,p1,i2); p1[i2]=0; ++vlen;
      break;
    case 'x': ok=1;
      // <text1> <text2> ?x : <text2> <text1>
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?x: Param",*y,*x);
      i1=val[vlen-2].len; p1=val[vlen-2].val;
      val[vlen-2].len=val[vlen-1].len;
      val[vlen-2].val=val[vlen-1].val;
      val[vlen-1].len=i1; val[vlen-1].val=p1;
      break;
    case 'p': ok=1;
      // <text> ?p
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?p: Param",*y,*x);
      MemRel(val[vlen-1].val); --vlen;
      break;
    case 's': ok=1;
      // <text1> <text2> ?s : <text1_text2>
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?s: Param",*y,*x);
      i1=val[vlen-1].len+val[vlen-2].len;
      if (!(p1=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?s: Nomem",*y,*x);
      MemCpy(val[vlen-2].val,p1,val[vlen-2].len);
      MemCpy(val[vlen-1].val,p1+val[vlen-2].len,val[vlen-1].len);
      MemRel(val[vlen-1].val); MemRel(val[vlen-2].val);
      val[vlen-2].len=i1; val[vlen-2].val=p1; p1[i1]=0; --vlen;
      break;
    case '!': ok=1;
      // <text1> <text2> ?! : <num>
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?!: Param",*y,*x);
      p2=StrCmp(p1=val[vlen-1].val,val[vlen-2].val);
      if (p2)
      { i1=p2-p1; p1+=i1;
        p2=val[vlen-2].val+i1;
        i1=(*p1>*p2)?1:-1;
      } else i1=0;
      MemRel(val[vlen-1].val);
      MemRel(val[vlen-2].val);
      i1=StrLen(p1=Num2Str(1,10,i1,tmp,0));
      if (!(p2=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?!: Nomem",*y,*x);
      val[vlen-2].len=i1; val[vlen-2].val=p2;
      MemCpy(p1,p2,i1); p2[i1]=0; --vlen;
      break;
    case '$': ok=1;
      // <text> ?$
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?$: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if (blen+i1>BUFLEN)
        ERR2("Error: (%lu,%lu): ?$: BufLen",*y,*x);
      MemCpy(buf+bpos,buf+bpos+i1,blen-bpos);
      MemCpy(p1,buf+bpos,i1); blen+=i1;
      MemRel(p1); --vlen;
      break;
    case '/': ok=1;
      // <text_if> <text_el> <num> ?/
      if (vlen<3)
        ERR2("Error: (%lu,%lu): ?/: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if (Str2Num(p1))
      { MemRel(val[--vlen].val);
        MemRel(val[--vlen].val); --vlen;
        i1=val[vlen].len; p1=val[vlen].val;
      } else
      { MemRel(val[--vlen].val); --vlen;
        i1=val[vlen].len; p1=val[vlen].val;
        MemRel(val[--vlen].val);
      }
      if (blen+i1>BUFLEN)
        ERR2("Error: (%lu,%lu): ?/: BufLen",*y,*x);
      MemCpy(buf+bpos,buf+bpos+i1,blen-bpos);
      MemCpy(p1,buf+bpos,i1); blen+=i1; MemRel(p1);
      break;
    case '@': ok=1;
      // <file> ?@
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?@: Param",*y,*x);
      p1=val[vlen-1].val;
      if (FileCheck(p1,&i1,NULL))
        ERR2("Error: (%lu,%lu): ?@: FileCheck",*y,*x);
      if (blen+i1>BUFLEN)
        ERR2("Error: (%lu,%lu): ?@: BufLen",*y,*x);
      MemCpy(buf+bpos,buf+bpos+i1,blen-bpos);
      if ((i2=FileOpen(FileOpenRead,p1))==-1)
        ERR2("Error: (%lu,%lu): ?@: FileOpen",*y,*x);
      if (FileRead(i2,buf+bpos,i1)==-1)
        ERR2("Error: (%lu,%lu): ?@: FileRead",*y,*x);
      FileClose(i2); blen+=i1; MemRel(p1); --vlen;
      break;
    case '?': ok=1;
      // <name> ?? : <text>
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ??: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if ((i2=mac1(p1,i1))==-1)
        ERR2("Error: (%lu,%lu): ??: MacNam",*y,*x);
      m1=mac+i2; if (!m1->nl)
        ERR2("Error: (%lu,%lu): ??: MacNam",*y,*x);
      MemRel(p1); i1=m1->tl;
      if (!(p1=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ??: Nomem",*y,*x);
      MemCpy(m1->txt,p1,i1); p1[i1]=0;
      val[vlen-1].len=i1; val[vlen-1].val=p1;
      break;
    case '=': ok=1;
      // <text> <name> ?=
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?=: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if (!i1 || i1>NAMLEN)
        ERR2("Error: (%lu,%lu): ?=: NamLen",*y,*x);
      if ((i2=mac1(p1,i1))==-1)
        ERR2("Error: (%lu,%lu): ?=: MacNum",*y,*x);
      m1=mac+i2; m1->sum=sum1(p1,i1);
      m1->nl=(N2)i1; MemCpy(p1,m1->nam,i1);
      MemRel(p1); vlen-=2;
      i1=val[vlen].len; p1=val[vlen].val;
      MemRel(m1->txt); m1->tl=i1; m1->txt=p1;
      break;
    case '+': ok=1;
      // <text> <name> ?+
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?+: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if (!i1 || i1>NAMLEN)
        ERR2("Error: (%lu,%lu): ?+: NamLen",*y,*x);
      if ((i2=mac2())==-1)
        ERR2("Error: (%lu,%lu): ?+: MacNum",*y,*x);
      m1=mac+i2; m1->sum=sum1(p1,i1);
      m1->nl=(N2)i1; MemCpy(p1,m1->nam,i1);
      MemRel(p1); vlen-=2;
      i1=val[vlen].len; p1=val[vlen].val;
      MemRel(m1->txt); m1->tl=i1; m1->txt=p1;
      break;
    case '-': ok=1;
      // <name> ?-
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?-: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      m1=NULL; if ((i2=mac1(p1,i1))!=-1)
      { m1=mac+i2; if (!m1->nl) i2=-1; }
      MemRel(p1); --vlen; if (i2==-1) break;
      m1->sum=0; m1->nl=0; m1->tl=0;
      MemRel(m1->txt); m1->txt=NULL;
      break;
    case '#': ok=1;
      // <num> ?# : <hnum>
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?#: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      i1=Str2Num(p1); MemRel(p1);
      i1=StrLen(p1=Num2Str(0,16,i1,tmp,0));
      if (!(p2=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?#: Nomem",*y,*x);
      val[vlen-1].len=i1; val[vlen-1].val=p2;
      MemCpy(p1,p2,i1); p2[i1]=0;
      break;
    case 'c': ok=1;
      // <num> ?c : <char>
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?c: Param",*y,*x);
      p1=val[vlen-1].val;
      i1=Str2Num(p1); MemRel(p1);
      if (!(p1=MemGet(1+1)))
        ERR2("Error: (%lu,%lu): ?c: Nomem",*y,*x);
      p1[0]=(N1)i1; p1[1]=0;
      val[vlen-1].len=1; val[vlen-1].val=p1;
      break;
    case 'n': ok=1;
      // <char> ?n : <num>
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?n: Param",*y,*x);
      p1=val[vlen-1].val;
      i1=(N1)*p1; MemRel(p1);
      i1=StrLen(p1=Num2Str(0,10,i1,tmp,0));
      if (!(p2=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?n: Nomem",*y,*x);
      val[vlen-1].len=i1; val[vlen-1].val=p2;
      MemCpy(p1,p2,i1); p2[i1]=0;
      break;
    case 'i': ok=1;
      // <ind1> <ind2> <text> ?i : <text>
      if (vlen<3)
        ERR2("Error: (%lu,%lu): ?i: Param",*y,*x);
      p1=val[vlen-3].val;
      i2=Str2Num(p1); MemRel(p1);
      p1=val[vlen-2].val;
      i3=Str2Num(p1); MemRel(p1);
      p1=val[vlen-1].val; i1=val[vlen-1].len;
      if (Typ(I4,i2)<0) i2+=i1;
      if (Typ(I4,i3)<0) i3+=i1;
      if (Typ(I4,i2)<0) i2=0;
      if (Typ(I4,i3)<0) i3=0;
      i3=i3-i2+1;
      if (Typ(I4,i3)<0) i3=0;
      if (i2>=i1) i3=0;
      if (!(p2=MemGet(i3+1)))
        ERR2("Error: (%lu,%lu): ?i: Nomem",*y,*x);
      MemCpy(p1+i2,p2,i3); p2[i3]=0;
      MemRel(p1); vlen-=2;
      val[vlen-1].len=i3; val[vlen-1].val=p2;
      break;
    case 'l': ok=1;
      // <text> ?l : <num>
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?l: Param",*y,*x);
      p1=val[vlen-1].val; i1=val[vlen-1].len;
      MemRel(p1);
      i1=StrLen(p1=Num2Str(0,10,i1,tmp,0));
      if (!(p2=MemGet(i1+1)))
        ERR2("Error: (%lu,%lu): ?l: Nomem",*y,*x);
      val[vlen-1].len=i1; val[vlen-1].val=p2;
      MemCpy(p1,p2,i1); p2[i1]=0;
      break;
    case '^': ok=1;
      // <ind> ?^ : <num>|<text><name>
      if (vlen<2 || vlen==VALNUM)
        ERR2("Error: (%lu,%lu): ?^: Param",*y,*x);
      p1=val[vlen-1].val;
      i1=Str2Num(p1); MemRel(p1);
      if (i1==-1)
      { m1=mac; i2=0;
        for (i1=0;i1<mlen;++i1,++m1)
          if (m1->nl) ++i2;
        i1=StrLen(p1=Num2Str(0,10,i2,tmp,0));
        if (!(p2=MemGet(i1+1)))
          ERR2("Error: (%lu,%lu): ?^: Nomem",*y,*x);
        val[vlen-1].len=i1; val[vlen-1].val=p2;
        MemCpy(p1,p2,i1); p2[i1]=0;
      } else
      { m1=mac; i2=i1; ++vlen;
        for (i1=0;i1<mlen;++i1,++m1)
        { if (!m1->nl) continue;
          if (i2) --i2; else break;
        }
        if (i1==mlen)
        { if (!(p1=MemGet(0+1)))
            ERR2("Error: (%lu,%lu): ?^: Nomem",*y,*x);
          val[vlen-2].len=0; val[vlen-2].val=p1; p1[0]=0;
          if (!(p1=MemGet(0+1)))
            ERR2("Error: (%lu,%lu): ?^: Nomem",*y,*x);
          val[vlen-1].len=0; val[vlen-1].val=p1; p1[0]=0;
        } else
        { if (!(p1=MemGet((i1=m1->tl)+1)))
            ERR2("Error: (%lu,%lu): ?^: Nomem",*y,*x);
          val[vlen-2].len=i1; val[vlen-2].val=p1;
          MemCpy(m1->txt,p1,i1); p1[i1]=0;
          if (!(p1=MemGet((i1=m1->nl)+1)))
            ERR2("Error: (%lu,%lu): ?^: Nomem",*y,*x);
          val[vlen-1].len=i1; val[vlen-1].val=p1;
          MemCpy(m1->nam,p1,i1); p1[i1]=0;
        }
      }
      break;
    case '~': ok=1;
      // <name> ?~ : 0|1
      if (vlen<1)
        ERR2("Error: (%lu,%lu): ?~: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if ((i1=mac1(p1,i1))==-1) i1='0'; else
      { m1=mac+i1; i1=(m1->nl?'1':'0'); }
      MemRel(p1); if (!(p1=MemGet(1+1)))
        ERR2("Error: (%lu,%lu): ?~: Nomem",*y,*x);
      val[vlen-1].len=1; val[vlen-1].val=p1;
      p1[0]=(N1)i1; p1[1]=0;
      break;
    case '%': ok=1;
      // ?%<name> : <text>
      i1=getm2(1,tmp,TMPLEN,x,y);
      if (i1==-1) return (-1);
      if ((i2=mac1(tmp,i1))==-1)
        ERR2("Error: (%lu,%lu): ?%%: MacNam",*y,*x);
      m1=mac+i2; if (!m1->nl)
        ERR2("Error: (%lu,%lu): ?%%: MacNam",*y,*x);
      i1=m1->tl; p1=m1->txt;
      if (blen+i1>BUFLEN)
        ERR2("Error: (%lu,%lu): ?%%: BufLen",*y,*x);
      MemCpy(buf+bpos,buf+bpos+i1,blen-bpos);
      MemCpy(p1,buf+bpos,i1); blen+=i1;
      break;
    case '(': ok=1;
      *spc=1;
      break;
    case ')': ok=1;
      *spc=0;
      break;
    /*case '1': ok=1;
      fprintf(stdout,"\nMacBeg:\n");
      for (i1=0;i1<mlen;++i1)
      { m1=mac+i1;
        if (!m1->nl) continue;
        fputc('`',stdout);
        for (i2=0;i2<m1->nl;++i2)
          fputc(m1->nam[i2],stdout);
        fprintf(stdout,"`\n  `");
        for (i2=0;i2<m1->tl;++i2)
          fputc(m1->txt[i2],stdout);
        fprintf(stdout,"`\n");
      }
      fprintf(stdout,"MacEnd:\n");
      break;
    case '2': ok=1;
      fprintf(stdout,"\nValBeg:\n");
      for (i1=0;i1<vlen;++i1)
      { fputc('`',stdout);
        for (i2=0;i2<val[i1].len;++i2)
          fputc(val[i1].val[i2],stdout);
        fprintf(stdout,"`\n");
      }
      fprintf(stdout,"ValEnd:\n");
      break;*/
    case '&': i1=i2=j1=j2=0;
      // ... <num1> <opc> ?& : <num>
      if (vlen<2)
        ERR2("Error: (%lu,%lu): ?&: Param",*y,*x);
      i1=val[vlen-1].len; p1=val[vlen-1].val;
      if (i1==1)
      { switch (*p1)
        { case '+':
          case '-':
          case '*':
          case '/':
          case '%':
          case '&':
          case '|':
          case '^':
          case '<':
          case '>': ok=1;
            MacOp3Beg; break;
        }
        switch (*p1)
        { case '+': i1+=i2; break;
          case '-': i1-=i2; break;
          case '*': i1*=i2; break;
          case '/':  if (!i2)
            ERR2("Error: (%lu,%lu): ?&: Div0",*y,*x);
            i1/=i2; break;
          case '%': if (!i2)
            ERR2("Error: (%lu,%lu): ?&: Div0",*y,*x);
            i1%=i2; break;
            break;
          case '&': i1&=i2; break;
          case '|': i1|=i2; break;
          case '^': i1^=i2; break;
          case '<': i1=(i1<i2); break;
          case '>': i1=(i1>i2); break;
          case 'n':
          case '!': ok=1;
            i1=Str2Num(val[vlen-2].val);
            switch (*p1)
            { case 'n': i1=-i1;
                i1=StrLen(p1=Num2Str(1,10,i1,tmp,0));
                break;
              case '!': i1=~i1;
                i1=StrLen(p1=Num2Str(0,10,i1,tmp,0));
                break;
            }
            if (!(p2=MemGet(i1+1)))
              ERR2("Error: (%lu,%lu): ?&: Nomem",*y,*x);
            MemRel(val[--vlen].val);
            MemRel(val[vlen-1].val);
            val[vlen-1].len=i1; val[vlen-1].val=p2;
            MemCpy(p1,p2,i1); p2[i1]=0; break;
        }
        switch (*p1)
        { case '+':
          case '-':
          case '*':
          case '/':
          case '%':
          case '&':
          case '|':
          case '^':
          case '<':
          case '>':
            MacOp3End; break;
        }
      } else
      if (i1==2)
      { if (p1[1]=='=')
        { switch (*p1)
          { case '=':
            case '!':
            case '<':
            case '>': ok=1;
              MacOp3Beg; break;
          }
          switch (*p1)
          { case '=': i1=(i1==i2); break;
            case '!': i1=(i1!=i2); break;
            case '<': i1=(i1<=i2); break;
            case '>': i1=(i1>=i2); break;
          }
          switch (*p1)
          { case '=':
            case '!':
            case '<':
            case '>':
              MacOp3End; break;
          }
        }
        if (p1[0]=='~')
        { switch (p1[1])
          { case '+':
            case '-':
            case '*':
            case '/':
            case '%':
            case '<':
            case '>': ok=1;
              MacOp3IBeg; break;
          }
          switch (*p1)
          { case '+': j1+=j2; break;
            case '-': j1-=j2; break;
            case '*': j1*=j2; break;
            case '/':  if (!j2)
              ERR2("Error: (%lu,%lu): ?&: Div0",*y,*x);
              j1/=j2; break;
            case '%': if (!j2)
              ERR2("Error: (%lu,%lu): ?&: Div0",*y,*x);
              j1%=j2; break;
              break;
            case '<': j1=(j1<j2); break;
            case '>': j1=(j1>j2); break;
          }
          switch (*p1)
          { case '+':
            case '-':
            case '*':
            case '/':
            case '%':
            case '<':
            case '>':
              MacOp3IEnd;
          }
        }
      } else
      if (i1==3)
      { if (p1[0]=='~' && p1[2]=='=')
        { if (p1[1]=='<' || p1[1]=='>')
          { ok=1;
            MacOp3IBeg;
            if (p1[1]=='<')
              j1=(j1<=j2);
            if (p1[1]=='>')
              j1=(j1>=j2);
            MacOp3IEnd;
          }
        }
      } 
      if (!ok) ERR2("Error: (%lu,%lu(: ?&: Opc",*y,*x);
      break;
  }
  if (ok) { *bk=0; out=-1; }

  return (ok);
}

//============= File =================================================

// ret: -1 - Error
// ret:  0 - File
// ret:  1 - Directory
N4 FileCheck(Str nam,N4 *len,N4 *tms)
{ struct stat st; N4 ret=0;

  if (!nam) return (-1);
  if (stat((char *)nam,&st)==-1) return (-1);
  if (S_ISDIR(st.st_mode)) ret=1;
  if (len) *len=st.st_size;
  if (tms)
  { if (ret) *tms=st.st_ctime;
    else *tms=st.st_mtime;
  }

  return (ret);
}

N4 FileOpen(N1 mod,Str nam)
{ int id,mod2;

  switch (mod)
  { case FileOpenRead :
      mod2=O_RDONLY;
      break;
    case FileOpenWrite :
      mod2=O_WRONLY;
      break;
    case (FileOpenRead|FileOpenWrite) :
      mod2=O_RDWR;
      break;
    default :
      return (-1);
  }
#if defined(___OS_WIN)
  mod2|=O_BINARY;
#endif
  if ((id=open((char *)nam,mod2))==-1) return (-1);

  return ((N4)(I4)id);
}

xx FileClose(N4 id)
{ if (id!=-1) close((int)id);
}

N4 FileRead(N4 id,Ptr buf,N4 len)
{ if (!buf && len) return (-1);
  return ((N4)(I4)read((I4)id,buf,len));
}

N4 FileWrite(N4 id,Ptr buf,N4 len)
{ if (!buf && len) return (-1);
  return ((N4)(I4)write((I4)id,buf,len));
}

//====================================================================
